package net.kelissa.divizor.train;

import java.util.ArrayList;
import java.util.List;

import net.kelissa.divizor.model.DivizorModel;
import net.kelissa.divizor.model.StatDivizor;
import net.kelissa.divizor.util.Const;
import net.kelissa.divizor.util.MathUtil;

public class TrainerComposite extends TrainerComponent
{

  private List<TrainerComponent> trainers;

  public TrainerComposite(DivizorModel divizor, int deep, int length)
  {
    this.divizor = divizor;
    this.deep = deep;
    this.length = length;
    this.trainers = new ArrayList<TrainerComponent>();

    fillChildren();
  }


  @Override
  public void train()
  {
    fillChildren();
    for (TrainerComponent trainer : this.trainers)
    {
      trainer.train();
    }
    checkBest();
    lifeAndDeath();
  }



  private void fillChildren()
  {
    int tot = this.length - this.trainers.size();
    for (int i = 0; i < tot; i++)
    {
      if(this.deep > 0)
      {
        //TODO aggiungerer e togliere cells
        this.trainers.add(new TrainerComposite(this.divizor.clone().perturbation(), this.deep-1, this.length) );
      }
      else
      {
        this.trainers.add(new TrainerLeaf(this.divizor.clone().perturbation()) );
      }
    }
  }

  private void checkBest()
  {
    StatDivizor statDivizor = MathUtil.calcStat(this.divizor);
    for (TrainerComponent trainer : this.trainers)
    {
      DivizorModel best = trainer.getDivizor();
      StatDivizor tmpStat = MathUtil.calcStat(best);
      if(tmpStat.getFitness() > statDivizor.getFitness())
      {
        if(tmpStat.getFitness() > statDivizor.getFitness())
        {
          this.age = 0;
          if(this.deep == Const.TRAIN_TREE_DEEP)
            System.out.println("EUREKA " + tmpStat.getFitness());
        }
        statDivizor = tmpStat;
        this.divizor = best;
      }
    }
    this.age += 1;
  }

  private void lifeAndDeath()
  {
    List<TrainerComponent> newList = new  ArrayList<TrainerComponent>();

    for (TrainerComponent trainer : this.trainers)
    {
      if(trainer.getAge() < Const.TRAIN_MAX_AGE)
      {
        newList.add(trainer);
      }
    }
    this.trainers = newList;
  }

}
